
---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------

-- systemEvent 是游戏的一个事件
local SystemEvent = Event:new()


SystemEvent.Name = ""
SystemEvent.MyTimer = nil

-- 事件的作用域,目前没有支持，以后扩展
SystemEvent.Scope = nil

-- 给事件绑定一个timeer,用来自动触发或者延迟出发一些逻辑

local allListerEventList = {};
function SystemEvent:SetTimer(timer)
    self.MyTimer = timer
end


-- 根据timer来更新一个事件
function SystemEvent:Update(deltTime)
    local timer = self.MyTimer
    if timer == nil then
        return
    end

    if timer.AlwaysRepeat == true then
        timer:UpdateAlways(self, deltTime)
    elseif timer.RepeatCount > 0 then
        timer:UpdateTimes(self, deltTime)
    elseif timer.RepeatCount <= 0 then
        return true
    end

    return false
end


function SystemEvent:Open(name, scope)

    self.Name = name

    if nil == scope then
        return
    end

    if nil == scope.Events then
        scope.Events = {}
    end

    if nil == scope.Events[self.Name] then
        scope.Events[self.Name] = true
    end

    self.Scope = scope

end


function SystemEvent:Close()

    local scope = self.Scope
    if nil == scope then
            return
    end

    if scope.Events ~= nil then
          scope.Events[self.Name] = nil
    end

    self.Scope = nil
end

function SystemEvent:Print()
    print("event name:"..self.Name)
    print("event scope:"..self.Scope)
    print("event responsers:"..self.Responsers:size())
    print("event triggers:"..self.Triggers:size())

    if self.MyTimer ~= nil then
        print("event Timer:")
        print("\tInterval:"..self.MyTimer.Interval)
        print("\tRepeatCount:"..self.MyTimer.RepeatCount)
        print("\tAlwaysRepeat:"..tostring(self.MyTimer.AlwaysRepeat))
        print("\tCurTime:"..self.MyTimer.CurTime)
    end
end

-----------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------

MyTimer = {}
--更新间隔
MyTimer.Interval = 0
--触发次数
MyTimer.RepeatCount = 0
--是否重复触发
MyTimer.AlwaysRepeat = false
--距上次触发后时间
MyTimer.CurTime = 0
--总时间
MyTimer.TotalTime = 0
--名称
MyTimer.Name = nil

function MyTimer:new(object)
    object = object or {}
    setmetatable(object, self)
    self.__index = self
    return object
end

function MyTimer:getName()
	return self.Name
end

function MyTimer:Clone()
    local newTimer = MyTimer:new()
    newTimer.Interval = self.Interval
    newTimer.AlwaysRepeat = self.AlwaysRepeat
    if not self.AlwaysRepeat then
        newTimer.RepeatCount = self.RepeatCount
    end
    return newTimer
end

function MyTimer:Always(interval,name)
    if interval == nil then
        interval = 0
    end

    local timer = MyTimer:new()
    timer.Interval = interval
    timer.AlwaysRepeat = true
    timer.Name = name
    return timer
end

function MyTimer:Times(interval, count)
    local timer = MyTimer:new()
    timer.Interval = interval
    timer.AlwaysRepeat = false
    timer.RepeatCount = count
    return timer
end

--只触发一次
function MyTimer:Once(interval)
    return MyTimer:Times(interval, 1)
end

--更新timer，条件允许则fire event
function MyTimer:UpdateTimes(event, deltTime)
    self.CurTime = self.CurTime + deltTime
    self.TotalTime = self.TotalTime + deltTime

    if self.CurTime >= self.Interval then
        if event ~= nil and event:Fire(self.CurTime, self.TotalTime) then
            self.RepeatCount = self.RepeatCount - 1
        end

        self.CurTime = 0
    end
end


function MyTimer:UpdateAlways(event, deltTime)

    self.CurTime = self.CurTime + deltTime
    self.TotalTime = self.TotalTime + deltTime

    if self.CurTime >= self.Interval then
        if event ~= nil then
            event:Fire(self.CurTime, self.TotalTime)
        end

        self.CurTime = 0
    end

end

--计时用
function MyTimer:Update(deltTime)
	self.CurTime = self.CurTime + deltTime
    self.TotalTime = self.TotalTime + deltTime
end

--判断是否满足触发条件
function MyTimer:CanTigger()
	if self.CurTime >= self.Interval  then
		self.CurTime = 0
		if self.AlwaysRepeat  then
			return true
		end
		if self.RepeatCount > 0 then
			self.RepeatCount = self.RepeatCount -1
			return true
		end
	end

	return false
end

---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
--事件系统，管理游戏内部的所有事件
local EventSystem = {}

local NeedUpdateEvents = {}
local NoNeedUpdateEvents = {}
local NewCreatedEvents = {}
local UpdateInternal = 0.01
local UpdatePassTime = 0.0


local SystemEventDispatcher = function(event)

    if event == nil then
        return
    end

    if event.MyTimer ~= nil and event:ResponserCount() > 0 then
        NeedUpdateEvents[event.Name] = event
        NoNeedUpdateEvents[event.Name] = nil
        NewCreatedEvents[event.Name] = nil
    elseif event:ResponserCount() > 0 then
        NeedUpdateEvents[event.Name] = nil
        NoNeedUpdateEvents[event.Name] = event
        NewCreatedEvents[event.Name] = nil
    elseif event.MyTimer ~= nil or event:TriggerCount() > 0 then
        NeedUpdateEvents[event.Name] = nil
        NoNeedUpdateEvents[event.Name] = nil
        NewCreatedEvents[event.Name] = event
    else
        EventSystem.Close(event.Name)
    end
end


function EventSystem.Open(name, scope)
    if nil == name then
        return nil
    end

    if NeedUpdateEvents[name] ~= nil then
        return NeedUpdateEvents[name]
    end

    if NoNeedUpdateEvents[name] ~= nil then
        return NoNeedUpdateEvents[name]
    end

    if NewCreatedEvents[name] ~= nil then
        return NewCreatedEvents[name]
    end

    local event = SystemEvent:new()

    event:Open(name, scope)

    NewCreatedEvents[name] = event
    return event
end



function EventSystem.Close(name)

    if nil == name then
        return
    end

    local event = EventSystem.Find(name)

    if nil == event then
      -- print("event not found: " .. name)
        return
    end
    event:Close()

    NeedUpdateEvents[name] = nil
    NoNeedUpdateEvents[name] = nil
    NewCreatedEvents[name] = nil

    --print("close event: " ..  name)
end

function EventSystem.CloseScope(scope)
    if nil == scope then
       return
    end

    if nil == scope.Events then
       return
    end

    for k,v in pairs(scope.Events) do
        EventSystem.Close(k)
    end
    scope = nil
end
function EventSystem.Find(name)

    if nil == name then
        return nil
    end

    if NeedUpdateEvents[name] ~= nil then
        return NeedUpdateEvents[name]
    end

    if NoNeedUpdateEvents[name] ~= nil then
        return NoNeedUpdateEvents[name]
    end

    if NewCreatedEvents[name] ~= nil then
        return NewCreatedEvents[name]
    end

    return nil
end


-- 绑定一个已经创建出来的事件
function EventSystem.Bind(name, func)
    local event = EventSystem.Find(name)

    if event ~= nil then
        event:Bind(func)
        SystemEventDispatcher(event)
        return true
    end

    return false
end

-- 解绑
function EventSystem.Unbind(name, func)
    local event = EventSystem.Find(name)

    if event ~= nil then
        event:Unbind(func)
        SystemEventDispatcher(event)
        return true
    end

    return false
end


--根据一个名字触发一个事件，仅触发非自动触发的事件
function EventSystem.Fire(name, ...)

    if nil == name then
        return
    end

    local event = NoNeedUpdateEvents[name]

    if event ~= nil then
        event:Fire(...)
    end

    return false
end

--给一个事件绑定的一个触发条件
function EventSystem.BindTrigger(name, func)
    local event = EventSystem.Find(name)
    if event ~= nil then
        event:BindTrigger(func)
        return true
    end

    return false
end

function EventSystem.UnbindTrigger(name, func)
    local event = EventSystem.Find(name)
    if event ~= nil then
        event:UnbindTrigger(func)
        return true
    end

    return false
end

-- 给一个事件设置一个timer
function EventSystem.SetTimer(name, timer)
    local event = EventSystem.Find(name)
    if event ~= nil then
        event:SetTimer(timer)
        SystemEventDispatcher(event)
        return true
    end

    return false
end


function EventSystem.Update(deltTime)
    UpdatePassTime = deltTime + UpdatePassTime
    if  UpdatePassTime < UpdateInternal then
        return
    end
    for k, event in pairs(NeedUpdateEvents) do
         if event ~= nil then
             local delete = event:Update(UpdatePassTime)
             if delete then
                 EventSystem.Close(k)
             end
         end
    end

    UpdatePassTime = 0.0

end

---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
--全局作用域，若没有制定作用域，则默认放在全局域下面
local GlobleScope = {}


--下面是一些给外部调用的全局函数
function UpdateEventSystem(deltTime)
    EventSystem.Update(deltTime)
end


function FireEvent(name, ...)
   -- return EventSystem.Fire(name, ...)
    local eventFunList = allListerEventList[name];
    if eventFunList ~= nil then
        for k,v in pairs(eventFunList) do
            if v and v.f ~= nil then
                if v.tb then
                    v.f(v.tb,...)
                else
                    v.f(...)
                end
            end
        end

    end
end
function CloseAllEvent()
    table.clear(allListerEventList)
end


function PrintEvent(name)
    local event = EventSystem.Find(name)
    if event ~= nil then
        return event:Print()
    end
end

--listen一个事件
---@param tbl table
 function ListenEvent(eventType, func, tbl)
--[[    scope = scope or GlobleScope
    if nil == scope then
        print( "listen event no scope")
        return nil
    end

    if nil == eventType then
       print("listen event no event")
    end

    if nil == func then
        print("listen event no func")
        return nil
    end

    local event = EventSystem.Open(eventType, scope)
    if event ~= nil then
        EventSystem.Bind(event.Name, func)
    end
    return event]]
    local evList = allListerEventList[eventType]
     if  evList == nil then
         evList = {}
         allListerEventList[eventType] = evList;
     end
    for k,v in pairs(evList) do
        if v.f == func and v.tb == tbl then
            return
        end
    end
     table.insert(evList,{f = func,tb = tbl});

 end

 --取消listen一个事件
 function StopListenEvent(eventType, func)
    if nil == eventType then
       print("listen event no event")
    end

    if nil == func then
        print("listen event no func")
        return nil
    end
	return EventSystem.Unbind(eventType, func)
 end

--添加一个自动触发的事件
function AddTriggerEvent(eventType ,timer, trigger, scope)

    scope = scope or GlobleScope
    if nil == scope then
        print( "add Trigger no scope")
        return nil
    end

    if nil == eventType then
       print("add Trigger no eventname")
    end

    if nil == timer then
        print("add Trigger no timer")
        return nil
    end


    local event = EventSystem.Open(eventType, scope)
    if nil == event then
       return nil
    end

    EventSystem.SetTimer(eventType, timer)
    EventSystem.BindTrigger(eventType, trigger)
    return event

end


--关闭一个事件
function CloseEvent(name,func,tb)

    local eventList = allListerEventList[name];
    if eventList ~= nil then
        for k,v in pairs(eventList) do
            if v.f == func then
                if v.tb == nil or v.tb == tb then
                    table.remove(eventList,k)
                    break
                end
            end
        end
        --table.removeByValue(eventList,func);
    end
    --EventSystem.Close(name)
end


--监听一个定时器
 function ListenTimer(timer, func,scope)

    scope = scope or GlobleScope
    if nil == scope then
        print("listen timer no scope")
        return nil
    end

    if nil == timer  then
        print("listen timer no timer")
        return nil
    end

    if nil == func then
        print("listen timer no func")
        return nil
    end

    local name = timer:getName() and timer:getName() or "Timer_" .. tostring(timer)
    local event = EventSystem.Open(name, scope)

    if event ~= nil then
        EventSystem.Bind(name, func)
    end

    EventSystem.SetTimer(name, timer)
    return event
 end

--关闭一个定时器
function CloseTimer(name)
    EventSystem.Close(name)
end

--关闭一个Scope下面的所有事件和定时器
function CloseScope(scope)
   EventSystem.CloseScope(scope)
end
